#ifndef __LIST_H__
#define __LIST_H__

#include <types.h>
#include <assert.h>

struct dl_node {
    struct dl_node  *next;
    struct dl_node  *prev;
};

typedef struct dl_node list_t;

#define LIST_DECLARE(list)	struct dl_node list = { &list , &list }
#define LIST_IS_EMPTY(list)	((list)->next == list)
#define LIST_FIRST(list)	((list)->next)
#define LIST_LAST(list)		((list)->prev)

#define list_insert(list, node) list_append(list, node)
#define list_first(list)	((list)->next)
#define list_next(list)		((list)->next)
#define list_empty(head)        ((head)->next == (head))
#define list_entry(p, type, member) \
    ((type *)((char *)(p) - (unsigned long)(&((type *)0)->member)))


#ifdef __cplusplus
extern "C" {
#endif

static void __inline list_tail(struct dl_node *head, struct dl_node *what) 
{
    assert(head != NULL);
    assert(what != NULL);
    
    head->prev->next = what;
    what->prev = head->prev;
    head->prev = what;
    what->next = head;
} 

static void __inline list_append(struct dl_node *to, struct dl_node *what) 
{
    assert(to != NULL);
    assert(what != NULL);

    what->next = to->next;
    what->prev = to;
    to->next = what;
    what->next->prev = what;	/* FIXED: */
}

static void __inline list_prepend(struct dl_node *to, struct dl_node *what) 
{
    assert(to != NULL);
    assert(what != NULL);

    what->next = to;
    what->prev = to->prev;

    to->prev = what;
    what->prev->next = what;	/* FIXED: */
}

static void __inline list_init(struct dl_node *list) 
{
    assert(list != NULL);

    list->next = list->prev = list;
}

static void __inline list_remove(struct dl_node *node)
{
    assert(node != NULL);
    
    if (node->prev == node ||
        node->next == node)
        return ;
        
    node->prev->next = node->next;
    node->next->prev = node->prev;
	node->next = node->prev = node;
}


/*void list_tail(struct dl_node *head, struct dl_node *what);
void list_append(struct dl_node *to, struct dl_node *what);
void list_prepend(struct dl_node *to, struct dl_node *what);
void list_init(struct dl_node *list);
void list_remove(struct dl_node *node);*/

#ifdef __cplusplus
}
#endif


#endif	/* __LIST_H__ */

